package com.lhkj.ct.meta.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lhkj.ct.base.cache.redis.RedisAccess;
import com.lhkj.ct.base.constants.CacheConstants;
import com.lhkj.ct.base.constants.ConfigConstants;
import com.lhkj.ct.base.model.dto.PageQuery;
import com.lhkj.ct.base.mybatis.extension.service.impl.IServiceImpl;
import com.lhkj.ct.base.utils.Asserts;
import com.lhkj.ct.base.utils.Convert;
import com.lhkj.ct.meta.admin.mapper.SysConfigMapper;
import com.lhkj.ct.meta.admin.model.entity.TblConfig;
import com.lhkj.ct.meta.admin.service.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jobob
 * @since 2023-09-12
 */
@Service
public class SysConfigServiceImpl extends IServiceImpl<SysConfigMapper, TblConfig> implements SysConfigService {

    @Resource
    private RedisAccess redisAccess;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        loadingConfigCache();
    }

    @Override
    public int insert(TblConfig entity) {
        int row = getBaseMapper().insert(entity);
        if (row > 0) {
            redisAccess.setCacheObject(getCacheKey(entity.getConfigKey()), entity.getConfigValue());
        }
        return row;
    }

    @Override
    public int updateById(TblConfig config) {
        TblConfig temp = getBaseMapper().selectById(config.getId());
        Asserts.assertFalse(null == temp, "参数配置不存在！");
        int row = getBaseMapper().updateById(config);
        if (row > 0) {
            if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
                redisAccess.deleteObject(getCacheKey(temp.getConfigKey()));
            }
            redisAccess.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
        return row;
    }

    @Override
    public IPage<TblConfig> selectConfigPage(TblConfig config, PageQuery pageQuery) {
        LambdaQueryWrapper<TblConfig> wrapper = new LambdaQueryWrapper<TblConfig>()
                // 参数名
                .like(StringUtils.isNotBlank(config.getConfigName()), TblConfig::getConfigName, config.getConfigName())
                // 参数key
                .like(StringUtils.isNotBlank(config.getConfigKey()), TblConfig::getConfigKey, config.getConfigKey())
                // 参数类型
                .eq(Objects.nonNull(config.getConfigType()), TblConfig::getConfigType, config.getConfigType());
        // 创建时间
//        List<Date> dates = pageQuery.convertDateTimes();
//        if (!dates.isEmpty()) {
//            wrapper.between(TblConfig::getCreateTime, dates.get(0), dates.get(1));
//        }
        return getBaseMapper().selectPage(generatePage(pageQuery), wrapper);
    }

    @Override
    public String selectConfigByKey(String configKey) {
        String configValue = Convert.toStr(redisAccess.getCacheObject(getCacheKey(configKey)));
        if (StringUtils.isNotEmpty(configValue)) {
            return configValue;
        }
        TblConfig config = new TblConfig();
        config.setConfigKey(configKey);
        TblConfig retConfig = getBaseMapper().selectOne(new LambdaQueryWrapper<TblConfig>().eq(TblConfig::getConfigKey, configKey));
        if (null != (retConfig)) {
            redisAccess.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
            return retConfig.getConfigValue();
        }
        return StringUtils.EMPTY;
    }

    @Override
    public boolean selectCaptchaEnabled() {
        String captchaEnabled = selectConfigByKey(ConfigConstants.CAPTCHA_ENABLED);
        if (StringUtils.isEmpty(captchaEnabled)) {
            return true;
        }
        return Convert.toBool(captchaEnabled);
    }

    @Override
    public boolean selectRegisterEnabled() {
        String captchaEnabled = selectConfigByKey(ConfigConstants.REGISTER_ENABLED);
        if (StringUtils.isEmpty(captchaEnabled)) {
            return true;
        }
        return Convert.toBool(captchaEnabled);
    }

    @Override
    public int selectPwdRetryLimit() {
        String limit = selectConfigByKey(ConfigConstants.USER_PASSWORD_RETRY_LIMIT_COUNT);
        return Convert.toInt(limit, 0);
    }

    @Override
    public int selectPwdRetryExceed() {
        String exceed = selectConfigByKey(ConfigConstants.USER_PASSWORD_RETRY_LIMIT_EXCEED);
        return Convert.toInt(exceed, 0);
    }

    @Override
    public boolean checkConfigKeyUnique(TblConfig config) {
        TblConfig target = getBaseMapper().selectOne(
                new LambdaQueryWrapper<TblConfig>().eq(TblConfig::getConfigKey, config.getConfigKey()).last("limit 1"));
        return target == null || StringUtils.equals(config.getId(), target.getId());
    }

    @Override
    public int removeByIds(Collection<? extends Serializable> idList) {
        Long count = getBaseMapper().selectCount(new LambdaQueryWrapper<TblConfig>()
                .select(TblConfig::getId)
                .in(TblConfig::getId, idList)
                .eq(TblConfig::getConfigType, 1));
        Asserts.assertFalse(count > 0, "系统内置参数不可删除，如需删除请联系系统工程师！");
        return getBaseMapper().deleteBatchIds(idList);
    }

    /**
     * 加载参数缓存数据
     */
    @Override
    public void loadingConfigCache() {
        List<TblConfig> configsList = getBaseMapper().selectList(new QueryWrapper<>());
        for (TblConfig config : configsList) {
            redisAccess.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
        }
    }

    /**
     * 清空参数缓存数据
     */
    @Override
    public void clearConfigCache() {
        Collection<String> keys = redisAccess.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redisAccess.deleteObject(keys);
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        clearConfigCache();
        loadingConfigCache();
    }


    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }
}
